home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1320 / 1320.xpi / components / gmParser.js < prev    next >
Text File  |  2010-01-22  |  13KB  |  360 lines

  1. // Gmail Manager
  2. // By Todd Long <longfocus@gmail.com>
  3. // http://www.longfocus.com/firefox/gmanager/
  4.  
  5. // Extension version
  6. const EXTENSION_VERSION = "0.6";
  7.  
  8. // Version where the preferences file was first introduced
  9. const DEFAULT_VERSION = "0.5";
  10.  
  11. // XML content type
  12. const XML_CONTENT_TYPE = "text/xml";
  13.  
  14. // XPath result types
  15. const STRING_TYPE = Components.interfaces.nsIDOMXPathResult.STRING_TYPE;
  16. const UNORDERED_NODE_SNAPSHOT_TYPE = Components.interfaces.nsIDOMXPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;
  17.  
  18. function gmParser()
  19. {
  20.   // Load the parsing services
  21.   this._logger = Components.classes["@longfocus.com/gmanager/logger;1"].getService(Components.interfaces.gmILogger);
  22.   this._converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  23.   this._domParser = Components.classes['@mozilla.org/xmlextras/domparser;1'].getService(Components.interfaces.nsIDOMParser);
  24.   this._domSerializer = Components.classes['@mozilla.org/xmlextras/xmlserializer;1'].getService(Components.interfaces.nsIDOMSerializer);
  25.   
  26.   // Initialize the converter
  27.   this._converter.charset = "UTF-8";
  28.   
  29.   // Initialize the transforms directory
  30.   var directoryService = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
  31.   this._transformsDir = directoryService.get("ProfD", Components.interfaces.nsIFile);
  32.   this._transformsDir.append("extensions");
  33.   this._transformsDir.append("{582195F5-92E7-40a0-A127-DB71295901D7}");
  34.   this._transformsDir.append("defaults");
  35.   this._transformsDir.append("transforms");
  36.   
  37.   // Check if the transforms directory exists
  38.   if (!this._transformsDir.exists())
  39.   {
  40.     // This is used for development
  41.     this._transformsDir = directoryService.get("ProfD", Components.interfaces.nsIFile);
  42.     this._transformsDir.append("gmanager");
  43.     this._transformsDir.append("transforms");
  44.   }
  45. }
  46. gmParser.prototype = {
  47.   get emptyDoc()
  48.   {
  49.     return this._domParser.parseFromString(
  50.         '<?xml version="1.0"?>\n' + 
  51.         '<prefs version="' + EXTENSION_VERSION + '">\n' + 
  52.         this._domSerializer.serializeToString(this.globalNode) + 
  53.         '</prefs>', XML_CONTENT_TYPE);
  54.   },
  55.   
  56.   get globalNode()
  57.   {
  58.     return this._domParser.parseFromString(
  59.         '  <account type="global">\n' + 
  60.         '    <pref id="general-hide-context-menu" value="false"/>\n' + 
  61.         '    <pref id="general-hide-tools-menu" value="false"/>\n' + 
  62.         '    <pref id="general-auto-login" value="false"/>\n' + 
  63.         '    <pref id="compose-tab-location" value="existing"/>\n' + 
  64.         '    <pref id="compose-mailto-links" value="false"/>\n' + 
  65.         '    <pref id="compose-mailto-default" value=""/>\n' + 
  66.         '    <pref id="compose-context-menu" value="false"/>\n' + 
  67.         '    <pref id="security-never-save-passwords" value="false"/>\n' + 
  68.         '    <pref id="security-secured-connection" value="true"/>\n' + 
  69.         '    <pref id="toolbar-auto-login" value="true"/>\n' + 
  70.         '    <pref id="toolbar-auto-check" value="true"/>\n' + 
  71.         '    <pref id="toolbar-auto-switch" value="false"/>\n' + 
  72.         '    <pref id="toolbar-left-click" value="background"/>\n' + 
  73.         '    <pref id="toolbar-middle-click" value="check-messages"/>\n' + 
  74.         '    <pref id="toolbar-reset-unread-count" value="false"/>\n' + 
  75.         '  </account>\n', XML_CONTENT_TYPE).documentElement;
  76.   },
  77.   
  78.   get accountNode()
  79.   {
  80.     return this._domParser.parseFromString(
  81.         '  <account>\n' + 
  82.         '    <pref id="general-auto-login" value="false"/>\n' + 
  83.         '    <pref id="toolbar-display" value="true"/>\n' + 
  84.         '    <pref id="toolbar-toolbar-id" value="status-bar"/>\n' + 
  85.         '    <pref id="toolbar-placement" value="always-last"/>\n' + 
  86.         '    <pref id="toolbar-specific-position" value="0"/>\n' + 
  87.         '    <pref id="toolbar-account-hide-unread-count" value="false"/>\n' + 
  88.         '    <pref id="toolbar-account-hide-alias" value="false"/>\n' + 
  89.         '    <pref id="toolbar-tooltip-show-labels" value="true"/>\n' + 
  90.         '    <pref id="toolbar-tooltip-show-snippets" value="true"/>\n' + 
  91.         '    <pref id="toolbar-unread-count-inbox" value="true"/>\n' + 
  92.         '    <pref id="toolbar-unread-count-spam" value="false"/>\n' + 
  93.         '    <pref id="toolbar-unread-count-labels" value="false"/>\n' + 
  94.         '    <pref id="notifications-check" value="true"/>\n' + 
  95.         '    <pref id="notifications-check-interval" value="15"/>\n' + 
  96.         '    <pref id="notifications-display-snippets" value="true"/>\n' + 
  97.         '    <pref id="notifications-sounds" value="false"/>\n' + 
  98.         '    <pref id="notifications-sounds-file" value=""/>\n' + 
  99.         '  </account>\n', XML_CONTENT_TYPE).documentElement;
  100.   },
  101.   
  102.   open: function(aFile)
  103.   {
  104.     var doc = null;
  105.     
  106.     // Check if the specified file exists
  107.     if (aFile && aFile.exists())
  108.     {
  109.       var docTemp = this._readFileToXML(aFile);
  110.       
  111.       if (docTemp)
  112.       {
  113.         var docElementTemp = docTemp.documentElement;
  114.         
  115.         if (docElementTemp && !docElementTemp.hasAttribute("version"))
  116.           docElementTemp.setAttribute("version", DEFAULT_VERSION);
  117.         
  118.         docTemp = this._transform(docTemp);
  119.         
  120.         if (this._validate(docTemp))
  121.           doc = docTemp;
  122.       }
  123.     }
  124.     
  125.     return doc;
  126.   },
  127.   
  128.   save: function(aFile, aDoc)
  129.   {
  130.     return this._writeXMLToFile(aFile, aDoc);
  131.   },
  132.   
  133.   _readFileToXML: function(aFile)
  134.   {
  135.     var doc = null;
  136.     var fiStream = null;
  137.     var siStream = null;
  138.     
  139.     try {
  140.       var data = new String();
  141.       
  142.       // Load the input streams
  143.       fiStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
  144.       siStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
  145.       
  146.       // Initialize the input streams
  147.       fiStream.init(aFile, 1, 0, false);
  148.       siStream.init(fiStream);
  149.       
  150.       while (siStream.available() > 0)
  151.       {
  152.         // Read the data from the input stream
  153.         var chunk = siStream.read(siStream.available());
  154.         data += this._converter.ConvertToUnicode(chunk);      
  155.       }
  156.       
  157.       // Convert the XML string to DOM document
  158.       doc = this._domParser.parseFromString(data, XML_CONTENT_TYPE);
  159.     } catch(e) {
  160.       // There was an error reading from the file
  161.       doc = null;
  162.     } finally {
  163.       // Make sure the input streams are closed
  164.       if (!fiStream)
  165.         fiStream.close();
  166.       if (!siStream)
  167.         siStream.close();
  168.     }
  169.     
  170.     // Return the DOM document
  171.     return doc;
  172.   },
  173.   
  174.   _writeXMLToFile: function(aFile, aDoc)
  175.   {
  176.     var success = false;
  177.     var foStream = null;
  178.     
  179.     try {
  180.       // Convert the DOM document to XML string
  181.       var data = this._domSerializer.serializeToString(aDoc);
  182.       
  183.       // Load the output stream
  184.       foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
  185.       
  186.       // Initialize the output stream
  187.       foStream.init(aFile, 0x02 | 0x08 | 0x20, 0664, 0); // wronly | create | truncate
  188.       
  189.       // Write the data to file
  190.       var chunk = this._converter.ConvertFromUnicode(data);
  191.       foStream.write(chunk, chunk.length);
  192.       
  193.       // Make sure all of the data has been written
  194.       var fin = this._converter.Finish();
  195.       if (fin && fin.length > 0)
  196.         foStream.write(fin, fin.length);
  197.       
  198.       // Success for writing to the file
  199.       success = true;
  200.     } catch(e) {
  201.       // There was an error writing to the file
  202.       success = false;
  203.     } finally {
  204.       // Make sure the output stream is closed
  205.       if (!foStream)
  206.         foStream.close();
  207.     }
  208.     
  209.     // Return if successful or not
  210.     return success;
  211.   },
  212.   
  213.   _validate: function(aDoc)
  214.   {
  215.     var globalResult = this._xpath(aDoc, "/prefs/account[@type=\"global\"]", UNORDERED_NODE_SNAPSHOT_TYPE);
  216.     
  217.     // Check if the global account is defined (required)
  218.     if (globalResult && globalResult.snapshotLength == 1)
  219.     {
  220.       var globalNode = globalResult.snapshotItem(0);
  221.       var nodeIdResults = this._xpath(this.globalNode, "/account/pref/@id", UNORDERED_NODE_SNAPSHOT_TYPE);
  222.       
  223.       // Validate the global account preferences
  224.       if (this._validateIds(globalNode, nodeIdResults))
  225.       {
  226.         var accountsResult = this._xpath(aDoc, "/prefs/account[@type and @email and @alias]", UNORDERED_NODE_SNAPSHOT_TYPE);
  227.         
  228.         // Check if any mail accounts are defined (not required)
  229.         if (accountsResult && accountsResult.snapshotLength > 0)
  230.         {
  231.           nodeIdResults = this._xpath(this.accountNode, "/account/pref/@id", UNORDERED_NODE_SNAPSHOT_TYPE);
  232.           
  233.           for (var i = 0; i < accountsResult.snapshotLength; i++)
  234.           {
  235.             var accountNode = accountsResult.snapshotItem(i);
  236.             
  237.             // Validate the mail account preferences
  238.             if (!this._validateIds(accountNode, nodeIdResults))
  239.               return false;
  240.           }
  241.         }
  242.         
  243.         return true;
  244.       }
  245.     }
  246.     
  247.     return false;
  248.   },
  249.   
  250.   _validateIds: function(aNode, aNodeIdResults)
  251.   {
  252.     if (!aNodeIdResults)
  253.       return false;
  254.     
  255.     for (var i = 0; i < aNodeIdResults.snapshotLength; i++)
  256.     {
  257.       var id = aNodeIdResults.snapshotItem(i).nodeValue;
  258.       var nodeIdResult = this._xpath(aNode, "./pref[@id=\"" + id + "\"]", UNORDERED_NODE_SNAPSHOT_TYPE);
  259.       
  260.       if (!nodeIdResult || nodeIdResult.snapshotLength != 1)
  261.         return false;
  262.     }
  263.     
  264.     return true;
  265.   },
  266.   
  267.   _transform: function(aDoc)
  268.   {
  269.     // Get the preferences version
  270.     var versionResult = this._xpath(aDoc, "/prefs/@version", STRING_TYPE);
  271.     
  272.     // Check if the preferences version exists
  273.     if (versionResult)
  274.     {
  275.       // Get the preferences transform file
  276.       var transformFile = this._transformsDir.clone();
  277.       transformFile.append("prefs-" + versionResult.stringValue + ".xsl");
  278.       
  279.       // Check if the transform file exists
  280.       if (versionResult.stringValue != EXTENSION_VERSION && transformFile.exists())
  281.       {
  282.         try {
  283.           // Import the transform file
  284.           var processor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"].createInstance(Components.interfaces.nsIXSLTProcessor);
  285.           processor.importStylesheet(this._readFileToXML(transformFile));
  286.           
  287.           // Transform the preferences
  288.           return this._transform(processor.transformToDocument(aDoc));
  289.         } catch(e) {
  290.           this._logger.log("There was an error transforming the preferences: " + e);
  291.           return null;
  292.         }
  293.       }
  294.     }
  295.     
  296.     // Return the transformed preferences
  297.     return aDoc;
  298.   },
  299.   
  300.   _xpath: function(aNode, aExpression, aType)
  301.   {
  302.     var results = null;
  303.     try {
  304.       // Evaluate the XPath expression
  305.       var xpathEvaluator = Components.classes["@mozilla.org/dom/xpath-evaluator;1"].createInstance(Components.interfaces.nsIDOMXPathEvaluator);
  306.       results = xpathEvaluator.evaluate(aExpression, aNode, null, aType, null);
  307.     } catch(e) {}
  308.     return results;
  309.   },
  310.   
  311.   QueryInterface: function(iid)
  312.   {
  313.     if (iid.equals(Components.interfaces.gmIParser) ||
  314.         iid.equals(Components.interfaces.nsISupports))
  315.       return this;
  316.     throw Components.results.NS_ERROR_NO_INTERFACE;
  317.   }
  318. }
  319.  
  320. var myModule = {
  321.   firstTime: true,
  322.   
  323.   myCID: Components.ID("{d0fe9af0-f7bc-11da-974d-0800200c9a66}"),
  324.   myDesc: "Preferences XML Parser",
  325.   myProgID: "@longfocus.com/gmanager/parser;1",
  326.   myFactory: {
  327.     createInstance: function(outer, iid) {
  328.       if (outer != null)
  329.         throw Components.results.NS_ERROR_NO_AGGREGATION;
  330.       
  331.       return (new gmParser()).QueryInterface(iid);
  332.     }
  333.   },
  334.   
  335.   registerSelf: function(compMgr, fileSpec, location, type)
  336.   {
  337.     if (this.firstTime) {
  338.       this.firstTime = false;
  339.       throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  340.     }
  341.     
  342.     compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  343.     compMgr.registerFactoryLocation(this.myCID, this.myDesc, this.myProgID, fileSpec, location, type);
  344.   },
  345.   
  346.   getClassObject: function(compMgr, cid, iid)
  347.   {
  348.     if (!cid.equals(this.myCID))
  349.       throw Components.results.NS_ERROR_NO_INTERFACE;
  350.     
  351.     if (!iid.equals(Components.interfaces.nsIFactory))
  352.       throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  353.     
  354.     return this.myFactory;
  355.   },
  356.   
  357.   canUnload: function(compMgr) { return true; }
  358. };
  359.  
  360. function NSGetModule(compMgr, fileSpec) { return myModule; }